package com.lzh.others.callBackTask;

import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import java.util.function.Supplier;

public class AsyncTest {

    /**
     * 这种方式调用方法并没有实现异步。调用方法的线程里会阻塞，等待该方法执行完毕
     * @param executeTask
     * @param <R>
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     * @throws TimeoutException
     */
    public static <R> Optional<R> invokeWithResult(CallbackTask<R> executeTask) throws ExecutionException, InterruptedException, TimeoutException {
        CompletableFuture<R> invoke = CompletableFuture.supplyAsync(() -> {
            return executeTask.execute();
        }).whenComplete((result, throwable) -> {
            executeTask.onSuccess(result);
        }).exceptionally(throwable -> {
            executeTask.onFailure(throwable);
            return null;
        });
        return Optional.ofNullable(invoke.get());
    }

    /**
     * 这种方式调用方法可以实现异步执行，在需要使用的地方在get出来
     *
     * @param executeTask
     * @return
     * @param <R>
     * @throws ExecutionException
     * @throws InterruptedException
     * @throws TimeoutException
     */
    public static <R> CompletableFuture<R> invokeComWithResult(CallbackTask<R> executeTask) throws ExecutionException, InterruptedException, TimeoutException {
        CompletableFuture<R> invoke = CompletableFuture.supplyAsync(() -> {
            return executeTask.execute();
        }).whenComplete((result, throwable) -> {
            executeTask.onSuccess(result);
        }).exceptionally(throwable -> {
            executeTask.onFailure(throwable);
            return null;
        });
        return invoke;
    }

    public static <R> Supplier<R> invokeSupWithResult(CallbackTask<R> executeTask) throws ExecutionException, InterruptedException, TimeoutException {
        CompletableFuture<R> invoked = invokeComWithResult(executeTask);
        Supplier<R> invoke = () -> {
            try {
                return invoked.get();
            } catch (Exception e) {
                return null;
            }
        };
        return invoke;
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        Supplier<Integer> supplier = invokeSupWithResult(new AddMethod());
        Integer i1 = null;
        for (int i = 0; i < 5000; i++) {
            System.out.println("主线程执行中...,i=" + i);
        }
        i1 = supplier.get();
        System.out.println("i = " + i1);
    }
}
